package mobile.game.core.gen;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import freemarker.template.Configuration;
import freemarker.template.Template;

/**
 * @author gzoro
 *
 * 自动生成工具的基类
 */
public abstract class GenBase {
	/** 编码 */
	private static final String PAGE_ENCODING = "UTF-8";
	/** 模板文件路径 */
	private static final String TEMP_DIR = "../../core/src/mobile/game/core/gen/templates";
	
	/** 插件指定生成的文件名 */
	public static String pluginDesFileName;

	/** 用户当前执行的所在路径 */
	public static String BASE_DIR = GenBase.class.getResource("/").getPath();
	
	/** 文件夹相关 */
	/** 配置源文件夹 */
	protected String packageName;
	/** 输出目标文件夹 */
	protected String targetDir;

	/** 文件生成相关 */
	/** 要放到模板的信息 */
	protected List<Map<String, Object>> rootMaps = new ArrayList<>();
	/** 是否能正常生成 */
	public boolean canGen;
	
	public GenBase(String packageName, String targetDir) {
		this.packageName = packageName;
		this.targetDir = targetDir;
	}
	
	/**
	 * 根据模版生成文件
	 * @param targetFileDir
	 * @param fileName
	 * @param tempName
	 * @param rootMap
	 * @throws Exception
	 */
	public static void writeFile(String targetFileDir, String fileName, String tempName, Object rootMap) throws Exception {
		/* 1，获取模板 */
		Configuration configuration = new Configuration(Configuration.VERSION_2_3_25);
		try {
			String tempDir = BASE_DIR + "/" + TEMP_DIR;
			configuration.setDirectoryForTemplateLoading(new File(tempDir));
			configuration.setEncoding(Locale.getDefault(), PAGE_ENCODING);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		
		// 获取模版
		Template temp = configuration.getTemplate(tempName, PAGE_ENCODING);
//		temp.setEncoding(PAGE_ENCODING);
		
		// 判断目标文件夹不存在 ，则新建文件夹
		File dir = new File(targetFileDir);
		if(!dir.exists()) {
			dir.mkdirs();
		}
		
		// 目标文件名(包含路径的名称)
		String fileFullName = targetFileDir + fileName;
		System.out.println("---------开始生成" + fileFullName + "文件......---------");
		
		// 根据模版生成文件
		File target = new File(fileFullName);
		Writer out = new OutputStreamWriter(new FileOutputStream(target), PAGE_ENCODING);
		temp.process(rootMap, out);
		out.flush();
		out.close();
		
		System.out.println("---------" + fileName + "文件生成完毕！---------\n");
	}
	
	/**
	 * 自动生成文件的具体方法
	 * @throws Exception 
	 */
	public void genFiles() throws Exception {
		// 判断能否生成
		if(!isCanGen()) {
			System.out.println("代码生成失败，请检查错误后重试！");
		} else {
			// 生成单一的全局代码，如ListenerInit、MsgReceiverInit
			genGlobalFile();
			
			// 遍历每个文件，生成对应的辅助代码
			for(Map<String, Object> rootMap : rootMaps) {
				genFileHandler(rootMap);
			}
		}
	}
	
	/**
	 * 对该类注解生成全局唯一的文件，子类可覆盖
	 * @param mapList
	 * @throws Exception
	 */
	private void genGlobalFile() throws Exception {
		// 判断是否为空
		if(this.rootMaps.isEmpty()) {
			return;
		}
		
		Map<String, Object> data = new HashMap<>();
		data.put("rootPackageName", this.packageName);
		data.put("methodsList", this.rootMaps);
		
		genGlobalFileHandler(data);
	}
	
	protected void genGlobalFileHandler(Map<String, Object> rootMaps) throws Exception {
		
	}
	
	/**
	 * 生成类的核心方法，各子类实现
	 * @param rootMap
	 * @throws Exception
	 */
	protected abstract void genFileHandler(Map<String, Object> rootMap) throws Exception;
	
	/**
	 * 判断能否成功生成代码
	 * @return
	 */
	public boolean isCanGen() {
		return canGen;
	}
	
}
